package com.unittec.zk.provider.service;

import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.ObjectMetadata;
import com.unittec.zk.provider.common.Md5;
import com.unittec.zk.provider.common.RedisKeyConstants;
import com.unittec.zk.provider.common.RedisUtils;
import com.unittec.zk.provider.common.ServiceIdConstants;
import com.unittec.zk.provider.scope.ThreadLocalScope;
import com.unittec.zk.provider.ApplicationContextProvider;
import com.unittec.zk.provider.log.Log;
import com.unittec.zk.sdk.auth.domain.SysDepartDto;
import com.unittec.zk.sdk.auth.domain.SysDicItemDto;
import com.unittec.zk.sdk.auth.domain.SysUserRes;
import com.unittec.zk.sdk.auth.request.*;
import com.unittec.zk.sdk.auth.response.*;
import com.unittec.zk.sdk.root.common.CommonConstant;
import com.unittec.zk.sdk.root.common.FieldConstants;
import com.unittec.zk.sdk.root.domain.GatewayRequest;
import com.unittec.zk.sdk.root.domain.Result;
import com.unittec.zk.sdk.root.enums.GatewayCode;
import com.unittec.zk.sdk.root.internal.exception.BusinessException;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author: wuxinwei
 * @CreateDate: 2019/12/25 15:47
 */
@Component
public class RootCommonUtils {

    @Resource
    private Log log;

    @Resource
    HystrixRestTemplateService hystrixRestTemplateService;

    @Resource
    RedisUtils redisUtils;

    @Async("taskExecutor")
    public void ansyUploadToOss(OSSClient ossClient, String bucketName, ObjectMetadata metadata, String path,
                                String fileName, InputStream is) {
        log.sysInfoLog("AnsyUploadToOss", "AnsyUploadToOss path:" + path);
        try {
            ossClient.putObject(bucketName, path, is, metadata);
        } catch (Exception e) {
            log.sysErrLog("AnsyUploadToOss", "AnsyUploadToOss error", e);
        }
    }

    /**
     * 发送消息
     *
     * @param userId
     * @param token
     * @param appId
     * @param appCode
     */
    @Async("taskExecutor")
    public void sendWebSocketMsg(String userId, String token, String appId, String appCode, String websocketMsgType) {
        Environment environment =
                (Environment) ApplicationContextProvider.getApplicationContext().getBean("environment");
        String gatewayUrl = environment.getProperty("websocket.gateway.dev.url");
        String[] activeProfiles = environment.getActiveProfiles();
        if (activeProfiles.length > 0) {
            for (String activeProfile : activeProfiles) {
                if (CommonConstant.ACTIVE_PROFILE_TEST.equalsIgnoreCase(activeProfile)) {
                    gatewayUrl = environment.getProperty("websocket.gateway.test.url");
                    log.sysInfoLog("webSocket sendWebSocketMsg", "当前环境:" + CommonConstant.ACTIVE_PROFILE_TEST);
                }
                if (CommonConstant.ACTIVE_PROFILE_PRO.equalsIgnoreCase(activeProfile)) {
                    gatewayUrl = environment.getProperty("websocket.gateway.pro.url");
                    log.sysInfoLog("webSocket sendWebSocketMsg", "当前环境:" + CommonConstant.ACTIVE_PROFILE_PRO);
                }
            }
        }

        log.sysInfoLog("webSocket sendWebSocketMsg", "sendWebSocketMsg  begin");
        CloseableHttpClient httpClient = HttpClients.createDefault();
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(15000).setConnectionRequestTimeout(10000)
                .setSocketTimeout(15000).build();
        JSONObject jsonParams = new JSONObject();
        jsonParams.put("appId", appId);
        jsonParams.put("app_id", appId);
        jsonParams.put("method", "125807");
        jsonParams.put("appkey", appCode);
        jsonParams.put("app_key", appCode);
        JSONObject content = new JSONObject();
        content.put("websocket_msg_type", websocketMsgType);
        content.put("user_id", userId);
        jsonParams.put("content", content);
        log.sysInfoLog("webSocket sendWebSocketMsg",
                "gatewayUrl:" + gatewayUrl + ",param:" + jsonParams.toJSONString());
        HttpPost httpPost = new HttpPost(gatewayUrl);
        httpPost.addHeader("Authorization", token);
        httpPost.setConfig(requestConfig);
        httpPost
                .setEntity(new StringEntity(jsonParams.toJSONString(), ContentType.create("application/json", "utf-8")));
        try {
            HttpResponse response = httpClient.execute(httpPost);
            if (response != null && response.getStatusLine().getStatusCode() == GatewayCode.SUCCESS.getCode()) {
                String result = EntityUtils.toString(response.getEntity());
                log.sysInfoLog("webSocket sendWebSocketMsg", "发送消息推送成功" + result);
            } else {
                log.sysInfoLog("webSocket sendWebSocketMsg",
                        "gatewayUrl:" + gatewayUrl + ",param:" + jsonParams.toJSONString());
                log.sysInfoLog("webSocket sendWebSocketMsg", "发送消息失败");
            }
        } catch (IOException e) {
            log.sysInfoLog("webSocket sendWebSocketMsg",
                    "gatewayUrl:" + gatewayUrl + ",param:" + jsonParams.toJSONString());
            log.sysErrLog("webSocket sendWebSocketMsg", "发送消息推送失败", e);
        }
    }

    /**
     * 获取用户的账号(该方法必须使用redis)
     *
     * @param userId
     * @return
     */
    public String getUserName(String userId) {
        String userName = "";
        try {
            if (StringUtils.isNotEmpty(userId)) {
                String key = RedisKeyConstants.USER_ID_KEY + userId;
                userName = redisUtils.get(key);
                if (StringUtils.isBlank(userName)) {
                    Res101106 res = getUserInfo(userId);
                    if (res != null) {
                        String userNameDb = res.getUsername();
                        if (StringUtils.isNotBlank(userNameDb)) {
                            userName = userNameDb;
                            redisUtils.set(key, userNameDb, 1000 * 60 * 60 * 24L);
                        }
                    }
                }
            }
        } catch (Exception e) {
            Res101106 res = getUserInfo(userId);
            if (res != null) {
                userName = res.getUsername();
            }
            log.sysErrLog("getRelaName", "获取用户的账号异常", e);
        }

        return userName;
    }

    /**
     * 获取用户的真实姓名(该方法必须使用redis)
     *
     * @param userId
     * @return
     */
    public String getRelaName(String userId) {
        String relaName = "";
        try {
            if (StringUtils.isNotEmpty(userId)) {
                String key = RedisKeyConstants.RELA_NAME_KEY + userId;
                relaName = redisUtils.get(key);
                if (StringUtils.isBlank(relaName)) {
                    Res101106 res = getUserInfo(userId);
                    if (res != null) {
                        String relaNameDb = res.getRealname();
                        if (StringUtils.isNotBlank(relaNameDb)) {
                            relaName = relaNameDb;
                            redisUtils.set(key, relaNameDb, 1000 * 60 * 60 * 24L);
                        }
                    }
                }
            }
        } catch (Exception e) {
            Res101106 res = getUserInfo(userId);
            if (res != null) {
                relaName = res.getRealname();
            }
            log.sysErrLog("getRelaName", "获取用户的真实姓名异常", e);
        }

        return relaName;
    }

    /**
     * 获取用户部门层级
     *
     * @param userId
     * @return
     */
    public int getDepartLevel(String userId) {
        int departLevel = 0;
        try {
            if (StringUtils.isNotEmpty(userId)) {
                String key = RedisKeyConstants.DEPART_LEVEL_KEY + userId;
                String departLevelTemp = redisUtils.get(key);
                if (StringUtils.isBlank(departLevelTemp)) {
                    Res101106 res = getUserInfo(userId);
                    if (res != null) {
                        String departLevelDb = res.getDepartLevel();
                        if (StringUtils.isNotBlank(departLevelDb)) {
                            departLevelTemp = departLevelDb;
                            redisUtils.set(key, departLevelDb, 1000 * 60 * 60 * 24L);
                        }
                    }
                } else {
                    departLevel = Integer.parseInt(departLevelTemp);
                }
            }
        } catch (Exception e) {
            Res101106 res = getUserInfo(userId);
            if (res != null) {
                String departLevelTemp = res.getDepartLevel();
                try {
                    departLevel = Integer.parseInt(departLevelTemp);
                } catch (NumberFormatException ex) {
                    log.sysErrLog("getDepartLevel", "转换用户的部门层级异常", e);
                    throw new BusinessException("转换用户的部门层级异常");
                }
            }
            log.sysErrLog("getDepartLevel", "获取用户的部门层级异常", e);
            throw new BusinessException("获取用户的部门层级异常");
        }

        return departLevel;
    }

    /**
     * 根据部门ID获取部门ID层级
     *
     * @param id
     * @return
     */
    public int getDepartLevelById(String id) {

        List<String> ids = new ArrayList<>();
        ids.add(id);
        List<SysDepartDto> list = getDepartNameByIds(ids);
        if (list == null || list.size() == 0) {
            throw new BusinessException("未查询到部门信息");
        }
        return list.get(0).getDepartLevel();

    }

    /**
     * 通过字典编码获取字典信息
     *
     * @param dicCode
     * @return
     */
    public List<SysDicItemDto> getDicItemList(String dicCode) {

        List<SysDicItemDto> sysDicItem = new ArrayList<>();
        sysDicItem = findDicItemListByDicCode(dicCode);
        if (sysDicItem == null || sysDicItem.size() == 0) {
            throw new BusinessException("未查询到部门信息");
        }
        return sysDicItem;

    }

    /**
     * 根据数据字典查询字典信息
     *
     * @param dicCode
     * @return
     */
    public List<SysDicItemDto> findDicItemListByDicCode(String dicCode) {
        try {
            GatewayRequest<Req101617> getWay = new GatewayRequest<>();
            Req101617 req101617 = new Req101617();
            req101617.setDicCode(dicCode);
            getWay.setMethod("101617");
            getWay.setContent(req101617);
            Result<Res101617> result101617 = hystrixRestTemplateService.exchange(
                    Md5.getMd5(FieldConstants.SYS_REQUEST_SOURCE_ID), ServiceIdConstants.AUTH_101617, getWay,
                    ThreadLocalScope.getAuthData(), new ParameterizedTypeReference<Result<Res101617>>() {
                    });
            if (result101617.isSuccess()) {
                if (null != result101617.getData().getObj()) {
                    if (result101617.getData().getObj().size() == 0) {
                        throw new BusinessException("未查询到字典信息");
                    }
                    return result101617.getData().getObj();
                } else {
                    throw new BusinessException("未查询到字典信息");
                }
            } else {
                return null;
            }
        } catch (Exception e) {
            log.sysErrLog("findDicItemListByDicCode", "查询字典信息异常", e);
            throw new BusinessException("查询字典信息异常");
        }
    }

    /**
     * 根据部门ID获取部门ID名称
     *
     * @param id
     * @return
     */
    public String getDepartNameById(String id) {

        List<String> ids = new ArrayList<>();
        ids.add(id);
        List<SysDepartDto> list = getDepartNameByIds(ids);
        if (list == null || list.size() == 0) {
            return null;
        }
        return list.get(0).getDepartName();
    }

    /**
     * 批量获取部门信息
     *
     * @param ids
     * @return
     */
    public Map<String, SysDepartDto> getDepartMapByIds(List<String> ids) {
        Map<String, SysDepartDto> map = new HashMap<>(16);
        if (ids == null || ids.size() == 0) {
            return map;
        }
        List<SysDepartDto> list = getDepartNameByIds(ids);
        if (list == null || list.size() == 0) {
            return map;
        }
        for (SysDepartDto dto : list) {
            map.put(dto.getId(), dto);
        }
        return map;
    }

    /**
     * 批量获取用户信息
     *
     * @param ids
     * @return
     */
    public Map<String, SysUserRes> getUserByIds(List<String> ids) {

        Map<String, SysUserRes> map = new HashMap<>();
        if (ids == null || ids.size() == 0) {
            return map;
        }

        GatewayRequest<Req101108> gatewayRequest = new GatewayRequest<>();
        Req101108 req101108 = new Req101108();
        req101108.setIdList(ids);
        gatewayRequest.setContent(req101108);

        Result<Res101108> result101408 = hystrixRestTemplateService.exchange(
                Md5.getMd5(FieldConstants.SYS_REQUEST_SOURCE_ID), ServiceIdConstants.AUTH_101108, gatewayRequest,
                ThreadLocalScope.getAuthData(), new ParameterizedTypeReference<Result<Res101108>>() {
                });

        List<SysUserRes> sysUserResList = result101408.getData().getList();
        if (sysUserResList != null && sysUserResList.size() > 0) {
            for (SysUserRes userRes : sysUserResList) {
                map.put(userRes.getId(), userRes);
            }
        }
        return map;
    }

    /**
     * 批量获取部门信息
     *
     * @param ids
     * @return
     */
    public List<SysDepartDto> getDepartNameByIds(List<String> ids) {

        try {
            GatewayRequest<Req101408> getWay = new GatewayRequest<>();
            Req101408 req101108 = new Req101408();
            req101108.setIds(ids);
            getWay.setMethod("101408");
            getWay.setContent(req101108);
            Result<Res101408> result101408 = hystrixRestTemplateService.exchange(
                    Md5.getMd5(FieldConstants.SYS_REQUEST_SOURCE_ID), ServiceIdConstants.AUTH_101408, getWay,
                    ThreadLocalScope.getAuthData(), new ParameterizedTypeReference<Result<Res101408>>() {
                    });

            if (result101408.isSuccess()) {
                if (null != result101408.getData().getList()) {
                    if (result101408.getData().getList().size() == 0) {
                        throw new BusinessException("未查询到部门信息");
                    }
                    return result101408.getData().getList();
                } else {
                    throw new BusinessException("未查询到部门信息");
                }
            } else {
                return null;
            }
        } catch (Exception e) {
            log.sysErrLog("getDepartNameByIds", "查询部门信息异常", e);
            throw new BusinessException("查询部门信息异常");
        }
    }

    /**
     * 获取用户信息
     *
     * @param userId
     * @return
     */
    public Res101106 getUserInfo(String userId) {
        try {
            GatewayRequest<Req101106> getWay = new GatewayRequest<>();
            Req101106 req101106 = new Req101106();
            req101106.setId(userId);
            getWay.setMethod("101106");
            getWay.setContent(req101106);
            Result<Res101106> result101106 = hystrixRestTemplateService.exchange(
                    Md5.getMd5(FieldConstants.SYS_REQUEST_SOURCE_ID), ServiceIdConstants.AUTH_101106, getWay,
                    ThreadLocalScope.getAuthData(), new ParameterizedTypeReference<Result<Res101106>>() {
                    });

            if (result101106.isSuccess()) {
                return result101106.getData();
            } else {
                throw new BusinessException("未查询用户信息");
            }
        } catch (Exception e) {
            log.sysErrLog("getUserInfo", "获取用户的信息异常", e);
            throw new BusinessException("查询用户信息异常");
        }

    }

    /**
     * 获取用户信息
     *
     * @param roleIds
     * @return
     */
    public Res101209 getRoleDetailsList(List<String> roleIds) {
        try {
            GatewayRequest<Req101209> getWay = new GatewayRequest<>();
            Req101209 req101209 = new Req101209();
            req101209.setRoleids(roleIds);
            getWay.setMethod("101209");
            getWay.setContent(req101209);
            Result<Res101209> result101209 = hystrixRestTemplateService.exchange(
                    Md5.getMd5(FieldConstants.SYS_REQUEST_SOURCE_ID), ServiceIdConstants.AUTH_101209, getWay,
                    ThreadLocalScope.getAuthData(), new ParameterizedTypeReference<Result<Res101209>>() {
                    });

            if (result101209.isSuccess()) {
                return result101209.getData();
            } else {
                throw new BusinessException("未查询到角色信息");
            }
        } catch (Exception e) {
            log.sysErrLog("getUserInfo", "获取角色的信息异常", e);
            throw new BusinessException("查询角色信息异常");
        }

    }

    /**
     * 根据用户ID获取该用户的部门ID
     *
     * @param userId
     * @return
     */
    public List<String> getUserDepartIds(String userId, Boolean recursionStatus) {

        try {
            GatewayRequest<Req101407> getWay = new GatewayRequest<>();
            Req101407 req101107 = new Req101407();
            req101107.setUserId(userId);
            req101107.setRecursionStatus(recursionStatus);
            getWay.setMethod("101407");
            getWay.setContent(req101107);
            Result<Res101407> result101407 = hystrixRestTemplateService.exchange(
                    Md5.getMd5(FieldConstants.SYS_REQUEST_SOURCE_ID), ServiceIdConstants.AUTH_101407, getWay,
                    ThreadLocalScope.getAuthData(), new ParameterizedTypeReference<Result<Res101407>>() {
                    });

            if (result101407.isSuccess()) {
                return result101407.getData().getDepartList();
            } else {
                throw new BusinessException("未查询用户部门信息");
            }
        } catch (Exception e) {
            log.sysErrLog("getUserInfo", "获取用户的信息异常", e);
            throw new BusinessException("查询用户部门信息异常");
        }

    }

    /**
     * 获取当前用户的部门，该系统一个用户 只有一个部门
     *
     * @param userId
     * @return
     */
    public String getUserDepart(String userId, Boolean recursionStatus) {
        List<String> list = getUserDepartIds(userId, recursionStatus);
        if (list != null && list.size() > 0) {
            return list.get(0);
        } else {
            return null;
        }
    }


    /**
     * 根据下级部门查询到它的二级部门
     */
    public String SecondDept(String deptId) {
        List<SysDepartDto> depts = this.findAllDept();
        Map<String, SysDepartDto> departDtoMap = depts.stream().collect(Collectors.toMap(SysDepartDto::getId, Function.identity()));

        while (true) {
            SysDepartDto curDept = departDtoMap.get(deptId);//当前部门
            SysDepartDto parentDept = departDtoMap.get(curDept.getParentId() != null ? curDept.getParentId() : "");//父部门
            String parentId = parentDept.getParentId();//父部门的父id
            if (parentId == null || parentId.equals("")) {
                return curDept.getId();
            } else {
                deptId = parentDept.getId();
            }
        }
    }

    public List<SysDepartDto> findAllDept() {
        GatewayRequest<Req101410> gatewayRequest = new GatewayRequest<>();
        Req101410 req101410 = new Req101410();
        gatewayRequest.setContent(req101410);
        gatewayRequest.setMethod("101410");
        Result<Res101410> result101410 = hystrixRestTemplateService.exchange(
                Md5.getMd5(FieldConstants.SYS_REQUEST_SOURCE_ID), ServiceIdConstants.AUTH_101410, gatewayRequest,
                ThreadLocalScope.getAuthData(), new ParameterizedTypeReference<Result<Res101410>>() {
                });

        if (result101410.isSuccess()) {
            return result101410.getData().getList();
        } else {
            throw new BusinessException("未查询到部门信息");
        }
    }


    /**
     * 根据字典code查询数据
     *
     * @param dicCode
     */
    public List<Map<String, Object>> getDicMap(String dicCode) {
        GatewayRequest<Req101616> gatewayRequest = new GatewayRequest<>();
        Req101616 req101616 = new Req101616();
        req101616.setDicCodes(Arrays.asList(dicCode));
        gatewayRequest.setContent(req101616);
        gatewayRequest.setMethod("101616");
        Result<Res101616> result101616 = hystrixRestTemplateService.exchange(
                Md5.getMd5(FieldConstants.SYS_REQUEST_SOURCE_ID), ServiceIdConstants.AUTH_101616, gatewayRequest,
                ThreadLocalScope.getAuthData(), new ParameterizedTypeReference<Result<Res101616>>() {
                });

        if (result101616.isSuccess()) {
            return result101616.getData().getDicMapList().get(dicCode);
        } else {
            throw new BusinessException("未查询到字典信息");
        }
    }

    /**
     * 根据用户id查询所属部门名称
     *
     * @param userId
     * @return
     */
    public String getDeptNameByUserId(String userId) {
        GatewayRequest<Req101411> gatewayRequest = new GatewayRequest<>();
        Req101411 req101411 = new Req101411();
        req101411.setUserId(userId);
        gatewayRequest.setContent(req101411);
        gatewayRequest.setMethod("101411");
        Result<Res101411> result101411 = hystrixRestTemplateService.exchange(
                Md5.getMd5(FieldConstants.SYS_REQUEST_SOURCE_ID), ServiceIdConstants.AUTH_101411, gatewayRequest,
                ThreadLocalScope.getAuthData(), new ParameterizedTypeReference<Result<Res101411>>() {
                });

        if (result101411.isSuccess()) {
            return result101411.getData().getDeptName();
        } else {
            throw new BusinessException("未查询用户以及部门");
        }
    }


    /**
     * 根据用户id查询所属部门名称
     *
     * @param userIds
     * @return
     */
    public List<Map<String, Object>> getDeptNameByUserIds(List<String> userIds) {
        GatewayRequest<Req101412> gatewayRequest = new GatewayRequest<>();
        Req101412 req101412 = new Req101412();
        req101412.setUserIds(userIds);
        gatewayRequest.setContent(req101412);
        gatewayRequest.setMethod("101412");
        Result<Res101412> result101412 = hystrixRestTemplateService.exchange(
                Md5.getMd5(FieldConstants.SYS_REQUEST_SOURCE_ID), ServiceIdConstants.AUTH_101412, gatewayRequest,
                ThreadLocalScope.getAuthData(), new ParameterizedTypeReference<Result<Res101412>>() {
                });

        if (result101412.isSuccess()) {
            return result101412.getData().getUserDepartMap();
        } else {
            throw new BusinessException("未查询用户以及部门");
        }
    }


}
